/**********************************************
 * Copyright (c) 2022 
 * All rights reserved. 
 * 
 * 文件名称：client.c 
 * 摘 要：mqtt温度上报主功能函数
 * 
 * 当前版本：1.0 
 * 作 者：任慧
 * 完成日期：2022年8月5日 
 *
 * ********************************************/

#include <getopt.h>
#include <signal.h>
#include <libgen.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#include "zlog.h"
#include "mosquitto.h"
#include "sqlite3.h"
#include "iniparser.h"
#include "dictionary.h"
#include "callback.h"
#include "platform.h"
#include "mqtt_conf.h"

#define PLATFORM "huaweiyun"


int g_stop = 0;
static inline void print_help(char *progname);
void sig_handle(int signum);

int main(int argc, char **argv)
{
	int                         con = 0;
	char                        progname[20];
	char                       *platforms = NULL;
	int                         platform;
	int                         opt;
	int                         daemon_run = 0;
	int                         rc = 0;

	struct mosquitto           *mosq = NULL;              //客户端实例
	mqtt_t                     *mqtt_ctx = NULL;

	struct option long_options[] = {
		{"background",no_argument,NULL,'b'},
		{"config",required_argument,NULL,'c'},
		{"help",no_argument,NULL,'h'},
		{"NULL",0,NULL,0}
	};

	mqtt_ctx = (mqtt_t *)malloc(sizeof(mqtt_t));
	memset(mqtt_ctx, 0, sizeof(*mqtt_ctx));
	memset(progname, 0, sizeof(progname));
	strcpy(progname, basename(argv[0]));
	platforms = PLATFORM;

	/*--------------------------------*
	 *        命令行参数解析          *
	 *--------------------------------*/
	while ((opt = getopt_long(argc, argv, "bc:h", long_options, NULL)) != -1)
	{
		switch (opt)
		{
			case 'b':
				daemon_run = 1;
				break;
			case 'c':
				platforms = optarg;
				break;
			case 'h':
				print_help(progname);
				return EXIT_SUCCESS;
			default :
				break;
		}
	}
	//platform
	platform = platform_check(platforms);
	if (platform < 0)
	{
		printf("error platform\n");
		free(mqtt_ctx);
		return -1;
	}

	if (get_mqtt_conf(mqtt_ctx, platform) < 0)
	{
		printf("get mqtt_conf failure:%s\n", strerror(errno));
		free(mqtt_ctx);
		return -2;
	}

	//zlog
	rc = zlog_init(mqtt_ctx->zlog_path);
	if (rc)
	{
		printf("init failed:%s\n",strerror(errno));
		free(mqtt_ctx);
		return -3;
	}

	mqtt_ctx->c = zlog_get_category("my_log");
	if (!mqtt_ctx->c)
	{
		printf("Get log failure\n");
		free(mqtt_ctx);
		zlog_fini();
		return -4;
	}

	//background
	if (daemon_run)
	{
		daemon(1,1);
	}

	//init
	if (mosquitto_lib_init() != MOSQ_ERR_SUCCESS)
	{
		zlog_error(mqtt_ctx->c,"mosquitto init failure:%s",strerror(errno));
		free(mqtt_ctx);
		zlog_fini();
		goto Cleanup;
	}
	zlog_info(mqtt_ctx->c,"mosquitto init successfully!");

	//mosquitto_new
	mosq = mosquitto_new(mqtt_ctx->client_id, true, (void *)mqtt_ctx);
	if (NULL == mosq)
	{
		zlog_error(mqtt_ctx->c, "new client failure:%s", strerror(errno));
		free(mqtt_ctx);
		mosquitto_lib_cleanup();
		zlog_fini();
		goto Cleanup;
	}
	zlog_info(mqtt_ctx->c,"mosquitto new successfully!");

	//username_pw_set
	if (mosquitto_username_pw_set(mosq, mqtt_ctx->username, mqtt_ctx->password) != MOSQ_ERR_SUCCESS)
	{
		zlog_error(mqtt_ctx->c, "set password failure:%s", strerror(errno));
		goto Cleanup;
	}
	zlog_info(mqtt_ctx->c,"set username password successfully!");

	//callback_set
	mosquitto_connect_callback_set(mosq, my_connect_callback);
	mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
        mosquitto_subscribe_callback_set(mosq,my_subscribe_callback);
        mosquitto_message_callback_set(mosq,my_message_callback);

	//signal
	signal(SIGTERM, sig_handle);
	signal(SIGINT, sig_handle);


	/*--------------------------------*
	 *           建立连接             *
	 *--------------------------------*/
	con = mosquitto_connect(mosq,mqtt_ctx->host,mqtt_ctx->port,mqtt_ctx->alive);
	if (con != MOSQ_ERR_SUCCESS)
	{
		zlog_error(mqtt_ctx->c, "connect failure:%s", strerror(errno));
		goto Cleanup;
	}
	zlog_info(mqtt_ctx->c, "connect successfully!");
        while (!g_stop)
        {
                mosquitto_loop(mosq,-1,1);
        }


	printf("Power off!\n");

Cleanup:
	free(mqtt_ctx);
	mosquitto_destroy(mosq);
	mosquitto_lib_cleanup();
	zlog_fini();
	return 0;
}

/**************************************************
 * 函数名：   sig_handle
 *
 * 函数功能： 将g_stop设为1，结束while循环使主函数退出
 *
 * 参数：     signum          信号
 *
 * 返回值:    无返回值
 **************************************************/
void sig_handle(int signum)
{
	printf("Catch signal [%d]\n", signum);
	g_stop = 1;
}

/**************************************************
 * 函数名：   printf_help
 *
 * 函数功能： 打印帮助信息
 *
 * 参数：     progname        功能名
 *
 * 返回值：   无返回值
 **************************************************/
static inline void print_help(char *progname)
{
	printf("\n*******************************************Help******************************************\n");
	printf("USAGE:%s [option]...\n", progname);
	printf("%s is a client program,which can be used to get the datas from huaweiyun platform\n", progname);
	printf("\nMandatory argument to long option are mandatory for short options too:\n");
	printf("-b[background]    set program running on background\n");
	printf("-c[config]      set the PORT of the client progname\n");
	printf("-h[help]      Display this help information\n");

	printf("\nExample:%s -b -t 30\n", progname);
	printf("*****************************************************************************************\n");
	printf("\n");

	return;
}

